import java.awt.Color;
import java.awt.Point;
import java.awt.image.BufferedImage;
import java.util.ArrayList;

public class Screen {
	
	private ArrayList<Grid> grids;
	
	Point upperLeft;
	Point downRight;
	
	int xCount; //keeps the number of grids on the x coordinate
	int yCount; //keeps the number of grids on the y coordinate
	
	int xGridSize;
	int yGridSize;
	
	BufferedImage capture = null;
	BufferedImage baseImage = null;
	
	public Screen(Point upperLeft, Point downRight, int xCount, int yCount, BufferedImage _capture, BufferedImage _base) {
		setScreen(upperLeft, downRight, xCount, yCount);
		grids = new ArrayList<Grid>(getGridCount());
		initializeGrids();
		capture = _capture;
		baseImage = _base;
	}
	
	private void initializeGrids() {
		//int counter = 0;
		
		for (int i=0; i<xCount; i++) {
			for (int j=0; j<yCount; j++) {
				Grid grid = new Grid(i,j);
				grid.setTopLeft(getUpperLeftOfGrid(i, j));
				grid.setBottomRight(getDownRightOfGrid(i, j));
				grids.add(grid);
				//Main.log("create grid: " + grid.getTopLeft().toString() + " " + grid.getBottomRight().toString());
			}
		}
	}
	
	//returns grid whose index is given
	public Grid getGrid(int x, int y) {
		
		for(int i=0; i<grids.size(); i++) {
			Grid grid = grids.get(i);
			Point index = grid.getGridIndex();
			if (index.getX() == x && index.getY() == y) {
				return grid;
			}
		}
		
		return null;
	}
	
	/*
	 * return the grids list
	 */
	public ArrayList<Grid> getGridList() {
		return grids;
	}
	
	//returns number of grids for current state of the screen
	private int getGridCount() {
		return xCount * yCount;
	}
	
	//set the current screen properties
	private void setScreen(Point upperLeft, Point downright, int xCount, int yCount) {
		Main.log("screen initilized x: " + xCount + " y: " + yCount);
		this.upperLeft = upperLeft;
		this.downRight = downright;
		this.xCount = xCount;
		this.yCount = yCount;
		calGridSize();
	}
	
	//calculates the grid sizes according to current values of upperleft, downright, xcount and ycount of the screen
	private void calGridSize() {
		if (xCount != 0 && yCount != 0) {
			xGridSize = (downRight.x - upperLeft.x) / xCount;
			yGridSize = (downRight.y - upperLeft.y) / yCount;
		}
	}
	
	/*
	 * determines whether or not grids are dirty by using current capture and baseImage
	 * it takes a grid sets whether or not it is dirty
	 */
	public void solveScreen() {
		
		for(int i=0; i < grids.size(); i++) {
			Grid grid = grids.get(i);
			
			//sample points for the given grid
			ArrayList<Point> samplePoints = getSamplePixels(grid.getGridIndex());
			Main.log("grid("+grid.getGridIndex().x+","+grid.getGridIndex().y+")");
			
			//create color array list for both capture and base image
			ArrayList<Integer> currentColors = new ArrayList<Integer>(samplePoints.size());
			ArrayList<Integer> baseColors = new ArrayList<Integer>(samplePoints.size());
			
			for(int j= 0; j < samplePoints.size(); j++) {
				Point point = samplePoints.get(j);
				int currentColor = capture.getRGB(point.x, point.y);
				Main.log("" +point+"");
				//Main.log("current: " + String.valueOf(currentColor));
				currentColors.add(j, currentColor);
				int baseColor = baseImage.getRGB(point.x, point.y);
				Main.log("base: " + baseColor + " current: " + currentColor);
				baseColors.add(j, baseColor);
			}
			
			grid.setContentColors(currentColors);
			grid.setEmptyColors(baseColors);
			
			//calculate the dirtiness of the grid
			//grid.isDirty();
			
		}
		
		/*
		 * test whether or not color arrays are properly set
		 */
		/*
		for(int i=0; i < grids.size(); i++) {
			Grid grid = grids.get(i);
			Main.log("grid("+grid.getGridIndex().x+","+grid.getGridIndex().y+")");
			for(int j= 0; j < grid.getEmptyColors().size(); j++) {
				Main.log("base: " + grid.getEmptyColors().get(j) + " current: " + grid.getContentColors().get(j));
			}
		}
		*/
		
	}
	
	//returns sample pixels points according to given x and y coordinate of grids 
	private ArrayList<Point> getSamplePixels(int x, int y) {
		
		ArrayList<Point> samples = new ArrayList<Point>();
		
		Point upperLeftPoint = getUpperLeftOfGrid(x, y);
		Point downRightPoint = getDownRightOfGrid(x, y);
		
		int unitSampleX = (downRightPoint.x - upperLeftPoint.x) / (BrainBuddy.sampleCount + 1);
		int unitSampleY = (downRightPoint.y - upperLeftPoint.y) / (BrainBuddy.sampleCount + 1);
		
		for (int i=1; i <= BrainBuddy.sampleCount; i++) {
			for (int j=1; j<= BrainBuddy.sampleCount; j++) {
				int sampleX = (unitSampleX * i) + upperLeftPoint.x;
				int sampleY = (unitSampleY * j) + upperLeftPoint.y;
				Point p = new Point(sampleX, sampleY);
				samples.add(p);
			}
		}
		
		return samples;
	}
	
	//returns sample pixels points according to given point of the grid
	private ArrayList<Point> getSamplePixels(Point point) {
		return getSamplePixels(point.x, point.y);
	}
	
	//returns the point which points to the upper left corner of the given grid
	//assumes that grid indexes start by 0
	private Point getUpperLeftOfGrid(int x, int y) {
		int upperX = (x * xGridSize) + upperLeft.x;
		int upperY = (y * yGridSize) + upperLeft.y;
		
		return new Point(upperX, upperY);
	}
	
	//returns the point which points to the down right corner of the given grid
	//assumes that grid indexes start by 0
	private Point getDownRightOfGrid(int x, int y) {
		int upperX = ((x + 1) * xGridSize) + upperLeft.x;
		int upperY = ((y + 1) * yGridSize) + upperLeft.y;
		
		return new Point(upperX, upperY);
	}
	

}
